/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package rnavigator.model;

import java.util.ArrayList;
import java.util.LinkedList;
import rnavigator.view.StructurePanel;

/**
 *
 * @author Elias la Cour
 */
public class Model {

    private Structure structure = null;
    StructurePanel structurePanel = null;
    private boolean debug = false;

    protected Structure findEdges(Structure structure) {
        this.structure = structure;
        return structure;
    }

    /**
     * returns a structure containing list of bases, 
     * list of knots (a base with info on other end of knot)
     * list of pseudoknots (a base with info on other end of knot)
     * @param structure takes a Structure as parameter
     */
    public Structure tieKnots(Structure structure) {
        String[] dotSequence = structure.getDotSequence();
        String[] baseSequence = structure.getBaseSequence();
        ArrayList<Base> bases = new ArrayList<Base>();
        LinkedList<Base> tmpBases = new LinkedList<Base>();
        LinkedList<Base> tmpPseudoBases = new LinkedList<Base>();
        //knots is sorted in no particular order
        LinkedList<Knot> knots = new LinkedList<Knot>();

        //@position used to set position for a nucleotide in the sequence
        int position = 0;
        //@mate used to store other end of the knot in a base class
        int mate;
        Base b = new Base();
        Base b2 = new Base();

        //initialize the arraylist, length+1 to give room for last base (3')
        //necessary to initialize otherwise set() method returns out of bounds error
        for (int i = 0; i <= dotSequence.length; i++) {
            bases.add(b);
        }

        Base start = new Base("5", 0);
        start.setKnot(true);
        bases.set(0, start);
        position++;


        //plots all info into bases array
        for (int i = position; i < dotSequence.length; i++) {
            b = new Base(baseSequence[i], position);

            if (dotSequence[i].equals("(")) {
                b.setKnot(true);
                bases.set(position, b);
                tmpBases.push(b);
            }
            if (dotSequence[i].equals("[")) {
                b.setPseudoKnot(true);
                bases.set(position, b);
                tmpPseudoBases.push(b);
            }
            if (dotSequence[i].equals(")")) {
                b.setKnot(true);
                b2 = tmpBases.pop();
                mate = b2.getPosition();
                b.setMate(mate);
                bases.set(position, b);
                //sets other end for mate base
                bases.get(mate).setMate(position);
                knots.push(new Knot(mate, position));
//                if (debug) {
//                    System.out.println("Knot found between: " + b.getPosition() + " " + b2.getPosition());
//                }
            }
            if (dotSequence[i].equals("]")) {
                b.setPseudoKnot(true);
                b2 = tmpPseudoBases.pop();
                mate = b2.getPosition();
                b.setMate(mate);
                bases.set(position, b);
                //sets other end for mate base
                bases.get(mate).setMate(position);
                knots.push(new Knot(mate, position,true));
//                if (debug) {
//                    System.out.println("Knot found between: " + b.getPosition() + " " + b.getPosition2());
//                }
            } else {
                //if dotSeq is ":"
                bases.set(position, b);
            }
            position++;
        }
        //stores and sets the last base to match first base: match between 5' and 3'
        b = new Base("3", position,0);
        b.setKnot(true);
        bases.set(position, b);
        bases.get(0).setMate(position);
        knots.push(new Knot(0,position));
        if(debug){
        for(Knot k : knots){
            System.out.println(k.toString());
        }
            
            }
        structure.setKnots(knots);
        structure.setBases(bases);

        if (debug) {
            System.out.println("Here is bases array:");
            for (Base bas : bases) {
                System.out.println(bas.getNucleotide() + " " + bas.getPosition() + " " + bas.getMate());
            }

        }
        return structure;
    }

    public void draftLinearFeynman(Structure st) {
    }

    public void draftCircularFeynman(Structure st) {
    }

    public void draftSecondaryStructure(Structure st) {
    }

    /**
     * @param structure the structure to set
     */
    public void setStructure(Structure structure) {
        this.structure = structure;
    }

    /**
     * @param debug the debug to set
     */
    public void setDebug(boolean debug) {
        this.debug = debug;
    }
}
